home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / program / swags_z.zip / TIMING.SWG / 0024_Super Precise Timing.pas < prev    next >
Pascal/Delphi Source File  |  1995-03-03  |  4KB  |  91 lines

  1. {
  2. MA>generate an interrupt (int $70?) 1000 times a second.
  3.  
  4. To speed up the system timer by a factor of 2, call "goosetimer(2)":
  5. }
  6. procedure goosetimer(goose: byte);    { Speed up system timer }
  7. var gooseword: word;
  8. begin
  9.   gooseword := $ffff div goose;       { Number of oscillations between ticks }
  10.   port[$43] := $36;                   { Set timer at new speed }
  11.   port[$40] := lo(gooseword);
  12.   port[$40] := hi(gooseword);
  13.   end;
  14. {
  15. In that procedure, you are telling the timer chip how many chip oscillations
  16. to wait before generating a "tick".  The default is to generate a "tick"
  17. every 65536 cycles, or 18.2 times per second (which also works out to 65536
  18. "ticks" per hour).  The drawback here is that the system clock will speed up
  19. accordingly, as will all functions dependent on the reception of "ticks".
  20. So a useful approach is to reprogram Int $08 such that additional "ticks"
  21. are not passed along to the standard system functions.  The way to
  22. accomplish that is to generate an "End of Interrupt" command on all the
  23. additional "ticks" instead of invoking the "original" Int 08h ISR.  The
  24. "End of Interrupt" command is a command that, much like the STI instruction,
  25. enables subsequent hardware interrupts to be processed.  Code is in order:
  26. }
  27. var goosefactor, ticklooper, cloktick: byte;
  28.     oldtimint: procedure;
  29.  
  30. { GOOSEFACTOR: the multiplication factor for the system speed
  31.   TICKLOOPER:  loops from 0 to GOOSEFACTOR - 1, resetting itself to 0
  32.                when it gets to GOOSEFACTOR -- used internally to determine
  33.                which "ticks" get passed along
  34.   CLOKTICK:    counts "ticks"; used in standardizing program timing
  35.   OLDTIMINT:   points to "original" Int 08h ISR }
  36. {--------------------------------------------------------------------------}
  37. procedure tickwait(time2wait: byte);    { delay until counter reaches }
  38. begin                                   { certain value }
  39.   repeat until cloktick >= time2wait;
  40.   cloktick := 0;                        { reset counter }
  41.   end;
  42. {--------------------------------------------------------------------------}
  43. procedure newtimint; interrupt;   { new timer interrupt }
  44. begin
  45.   if ticklooper > 0 then          { "suppress" this "tick" }
  46.     port[$20] := $20              { "End-of-Interrupt" command }
  47.    else begin
  48.     asm pushf; end;               { call old timer interrupt }
  49.     oldtimint;
  50.     end;
  51.   inc(cloktick);                  { update "tick" counter }
  52.   inc(ticklooper);
  53.   if ticklooper = goosefactor then ticklooper := 0;
  54.   end;
  55. {--------------------------------------------------------------------------}
  56. procedure initnewtimint(goose: byte); { set up new timer interrupt }
  57. var gooseword: word;
  58. begin
  59.   goosetimer(goose);                  { speed up timer }
  60.   goosefactor := goose;               { record speed increase }
  61.   getintvec($08, @oldtimint);         { record location of old interrupt }
  62.   setintvec($08, @newtimint);         { install new interrupt procedure }
  63.   cloktick := 0;                      { set counter to 0 }
  64.   ticklooper := 0;                    { set "extra tick" determiner to 0 }
  65.   end;
  66. {--------------------------------------------------------------------------}
  67. procedure setoldtimint;               { reset old timer }
  68. begin
  69.   setintvec($08, @oldtimint);         { original interrupt }
  70.   goosetimer(1);                      { original system speed }
  71.   end;
  72. {--------------------------------------------------------------------------}
  73. {
  74. To start new system timing, it's "initnewtimint"; to turn it off, it's
  75. "setoldtimint".  Most of the rest of that code is "internal": you don't need
  76. to worry about it.  The one procedure I haven't explained is "tickwait": it
  77. is used to standardize timing in programs from machine to machine by waiting
  78. for a given number of "ticks" to have gone by before continuing.  (Unlike
  79. "Delay", "tickwait" monitors an interrupt-driven counter, meaning the number
  80. of "ticks" is advanced even while other routines are executing.)  For
  81. example, this loop will print a new line every 18 "ticks", which are coming
  82. at twice the normal speed:
  83. }
  84. initnewtimint(2);
  85. cloktick := 0;
  86. while not keypressed do begin
  87.   writeln('18 more ticks have gone by');
  88.   tickwait(18);
  89.   end;
  90. setoldtimint;
  91.